/* -*- C++ -*- */

//=============================================================================
/*
 * @author Feloweria <380374483@qq.com>
 * Copyright (C) Feloweria
 * 
 * $ID 2013-06-27 10:38:21 AM
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * @version 1.0
 */
//=============================================================================


#include "Thread/ThreadMutex.h"
#include "Log/Log.h"

#ifdef __LINUX__
	#include <errno.h>
#endif

FELOWRIA_BEGIN

ThreadMutex::ThreadMutex()
{
#ifdef __LINUX__
		int32 result = pthread_mutex_init(&mutex,NULL);

		if(result != 0)
		{
			if(result == EINVAL)
				LOG_ERROR("ThreadMutex::ThreadMutex \"pthread_mutex_init\" the value specified by attr is invalid.");
			
			if(result == EBUSY)
				LOG_ERROR("ThreadMutex::ThreadMutex \"pthread_mutex_init\" the implementation has detected an attempt to reinitialize the object referenced by mutex, a previously initialized, but not yet destroyed, mutex.");
			
			if(result == EAGAIN)
				LOG_ERROR("ThreadMutex::ThreadMutex \"pthread_mutex_init\" the system lacked the necessary resources (other than memory) to initialize another mutex.");
			
			if(result == EPERM)
				LOG_ERROR("ThreadMutex::ThreadMutex \"pthread_mutex_init\" the caller does not have the privilege to perform the operation.");
			
			if(result == ENOMEM)
				LOG_ERROR("ThreadMutex::ThreadMutex \"pthread_mutex_init\" insufficient memory exists to initialize the mutex.");
			
			LOG_ERROR("ThreadMutex::ThreadMutex \"pthread_mutex_init\" LOG_ERROR");
			return ;
	}
#endif
	
#ifdef __WINDOWS__
		InitializeCriticalSection(&mutex);
#endif
}

ThreadMutex::~ThreadMutex()
{	
#ifdef __LINUX__
	int32 result = pthread_mutex_destroy(&mutex);
	
	if(result != 0)
	{
		if(result == EBUSY)
			LOG_ERROR("ThreadMutex::~ThreadMutex \"pthread_mutex_destroy\" The implementation has detected an attempt to destroy the object referenced by mutex while it is locked or referenced");
		
		if(result == EINVAL)
			LOG_ERROR("ThreadMutex::~ThreadMutex \"pthread_mutex_destroy\" the value specified by mutex is invalid");
			
		LOG_ERROR("ThreadMutex::~ThreadMutex \"pthread_mutex_destroy\" LOG_ERROR");
	}
#endif

#ifdef __WINDOWS__
	DeleteCriticalSection(&mutex);
#endif
}

void ThreadMutex::Lock()
{
#ifdef __LINUX__
	int32 result = pthread_mutex_lock(&mutex);
	
	if(result != 0)
	{
		if(result == EDEADLK)
			LOG_ERROR("ThreadMutex::Lock \"pthread_mutex_lock\" the current thread already owns the mutex.");
			
		if(result == EINVAL)
			LOG_ERROR("ThreadMutex::Lock \"pthread_mutex_lock\" the value specified by mutex does not refer to an initialized mutex object.");
		
		if(result == EAGAIN)
			LOG_ERROR("ThreadMutex::Lock \"pthread_mutex_lock\" the mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded");
	
		LOG_ERROR("ThreadMutex::Lock \"pthread_mutex_lock\" LOG_ERROR");
	}
#endif

#ifdef __WINDOWS__
	EnterCriticalSection(&mutex);
#endif
}

void ThreadMutex::UnLock()
{
#ifdef __LINUX__
	int32 result = pthread_mutex_unlock(&mutex);
	
	if(result != 0)
	{
		if(result == EPERM)
			LOG_ERROR("ThreadMutex::UnLock \"pthread_mutex_unlock\" the current thread does not own the mutex");
			
		if(result == EINVAL)
			LOG_ERROR("ThreadMutex::UnLock \"pthread_mutex_unlock\" the value specified by mutex does not refer to an initialized mutex object.");
		
		if(result == EAGAIN)
			LOG_ERROR("ThreadMutex::UnLock \"pthread_mutex_unlock\" the mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded");
	
		LOG_ERROR("ThreadMutex::UnLock \"pthread_mutex_unlock\" LOG_ERROR");
	}
#endif
	
#ifdef __WINDOWS__
	LeaveCriticalSection(&mutex);
#endif
}

bool ThreadMutex::TryLock()
{
#ifdef __LINUX__
	int32 result = pthread_mutex_trylock(&mutex);
	
	if(result != 0)
	{
		if(result == EBUSY)
			return false;
			
		if(result == EINVAL)
			LOG_ERROR("ThreadMutex::TryLock \"pthread_mutex_trylock\" the value specified by mutex does not refer to an initialized mutex object.");
		
		if(result == EAGAIN)
			LOG_ERROR("ThreadMutex::TryLock \"pthread_mutex_trylock\" the mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded");
		
		LOG_ERROR("ThreadMutex::TryLock \"pthread_mutex_trylock\" LOG_ERROR");
		return false;
	}

	return true;
#endif

#ifdef __WINDOWS__
	return TryEnterCriticalSection(&mutex) != 0;
#endif
}

FELOWRIA_END